#include <myhead.h>
#include "mypkg.h"
#include "server.h"
#include "mytime.h"
#include "print.h"
#include "service.h"

#define MAX_EVENTS 50 //epoll_wait一次最多可以返回的事件数量

static int server;

int server_startup(char* ip, int port){
	//socket
	server=socket(AF_INET, SOCK_DGRAM, 0);
	if(server==-1){
		perror("socket error");
		return -1;
	}

	//bind
	struct sockaddr_in addr;
	addr.sin_family=AF_INET;
	addr.sin_port=htons(port);
	addr.sin_addr.s_addr=inet_addr(ip);
	if(bind(server, (struct sockaddr*)&addr,sizeof(addr))==-1){
		perror("bind error");
		return -1;
	}

	int epfd=epoll_create1(EPOLL_CLOEXEC);
	if(epfd == -1){
		perror("epoll_create1 error");
		return -1;
	}

	struct epoll_event e1;
	e1.events=EPOLLIN;
	e1.data.fd=server;
	if(epoll_ctl(epfd, EPOLL_CTL_ADD, server, &e1)==-1){
		perror("epoll_ctl add error [1]");
		return -1;
	}

	//epoll_wait recv: 业务分发
	while(1){
		struct epoll_event eveArr[MAX_EVENTS];
		int num=epoll_wait(epfd, eveArr, MAX_EVENTS,-1);
		for(int i=0;i<num;i++){
			int fd=eveArr[i].data.fd;
			if(fd == server){
				//处理报文
				server_handleRecv();
			}
		}
	}
	//TODO 销毁关闭资源，虽然永远调用不到
}

//处理接受报文
void server_handleRecv(){
	//业务处理
	char buf[2048]={0};
	char errmsg[1024]={0};

	//
	struct sockaddr_in addr;
	socklen_t addrlen=sizeof(addr);
	//
	ssize_t cnt=recvfrom(server,buf,sizeof(buf),0,(struct sockaddr*)&addr, &addrlen);
	
	printf(">>%s 收到来自[%s:%d]的[%ld]字节:\n", mytime_now(), inet_ntoa(addr.sin_addr),ntohs(addr.sin_port), cnt);
	//打印报文
	print_hex(buf, cnt, 32);
	pkg_t* recvPkg=pkg_create();
	pkg_unpack(buf, recvPkg);
	//printf("msg_type=[%d],username=[%s],passwd=[%s]\n", recvPkg->msg_type, pkg_get(recvPkg, 0),
		//	pkg_get(recvPkg, 1));
	//printf("MSG_TYPE_LOGI=[%d]\n", MSG_TYPE_LOGIN);
	if(pkg_buf_check(buf, cnt, errmsg)!=0){
		print_red2("收到非法的报文", errmsg);
		return;
	}

	//TODO
	char sendbuf[4096]={0};
	int sendbufLen=4096;
	switch(recvPkg->msg_type){	
	case MSG_TYPE_LOGIN:
		user_service_login(pkg_get(recvPkg, 0), pkg_get(recvPkg, 1), inet_ntoa(addr.sin_addr), 
				ntohs(addr.sin_port), sendbuf, &sendbufLen);
		break;
	case MSG_TYPE_REG:
		user_service_reg(pkg_get(recvPkg,0), pkg_get(recvPkg,1), sendbuf, &sendbufLen);
		break;
	case MSG_TYPE_HEART:
		user_service_heart(pkg_get(recvPkg,0), inet_ntoa(addr.sin_addr), 
				ntohs(addr.sin_port), sendbuf,&sendbufLen);
		break;
	case MSG_TYPE_LOGOUT:
		user_service_logout(pkg_get(recvPkg,0), sendbuf, &sendbufLen);
		break;
	case MSG_TYPE_MYSSH:
		ssh_service_ssh(pkg_get(recvPkg,0), sendbuf, &sendbufLen);
		break;

	case MSG_TYPE_UPLOAD_START:
		ssh_service_upload_start(pkg_get(recvPkg,0),pkg_get(recvPkg, 1), sendbuf, &sendbufLen);
		break;
	case MSG_TYPE_UPLOAD_CONTENT:
		{int contLen=0;
		char* cont = pkg_getbuf(recvPkg,2,&contLen);
		ssh_service_upload_content(pkg_get(recvPkg,0),pkg_get(recvPkg, 1),cont, contLen, sendbuf, &sendbufLen);
		break;}
	case MSG_TYPE_UPLOAD_END:
		ssh_service_upload_end(pkg_get(recvPkg,0),pkg_get(recvPkg, 1),sendbuf, &sendbufLen);
		break;
	case MSG_TYPE_DOWNLOAD_START:
		ssh_service_download_start(pkg_get(recvPkg,0),pkg_get(recvPkg, 1), sendbuf, &sendbufLen);
		break;
	case MSG_TYPE_DOWNLOAD_CONTENT:{
		long start=0;
		char* s2=pkg_get(recvPkg, 2);
		sscanf(s2,"%ld",&start);
		printf("start=[%ld]\n", start);
		ssh_service_download_content(pkg_get(recvPkg,0),pkg_get(recvPkg, 1), start,sendbuf, &sendbufLen);
		break;}
	case MSG_TYPE_DOWNLOAD_END:
		ssh_service_download_end(pkg_get(recvPkg,0),pkg_get(recvPkg, 1), sendbuf, &sendbufLen);
		break;
	case MSG_TYPE_FRD_LIST:
		friend_service_list(pkg_get(recvPkg,0),sendbuf,&sendbufLen);
		break;
	case MSG_TYPE_FRD_ADD:
		friend_service_add(pkg_get(recvPkg,0),pkg_get(recvPkg,1),sendbuf,&sendbufLen);
		break;
	case MSG_TYPE_FRD_DELETE:
		friend_service_delete(pkg_get(recvPkg,0),pkg_get(recvPkg,1),sendbuf,&sendbufLen);
		break;
	case MSG_TYPE_FRD_CHAT:
		friend_service_chat(pkg_get(recvPkg,0),pkg_get(recvPkg,1),buf,cnt,sendbuf,&sendbufLen);
		break;
	case MSG_TYPE_GRP_CHAT:
		group_service_chat(pkg_get(recvPkg,0),pkg_get(recvPkg,1),buf,cnt,sendbuf, &sendbufLen);
		break;
	case MSG_TYPE_GRP_ADD:
		group_service_add(pkg_get(recvPkg,0),pkg_get(recvPkg,1),sendbuf,&sendbufLen);
		break;
	case MSG_TYPE_GRP_MYGRP:
		group_service_mygrp(pkg_get(recvPkg,0),sendbuf,&sendbufLen);
		break;
	case MSG_TYPE_GRP_MEM:
		group_service_mem(pkg_get(recvPkg,0),sendbuf,&sendbufLen);
		break;
	default:
		print_red("尚未支持的报文格式");
		pkg_free(recvPkg);
		return;
	}
	

	size_t sendCnt=sendto(server, sendbuf, sendbufLen, 0, (struct sockaddr*)&addr, sizeof(addr));
	printf("<<%s 发送[%s:%d][%ld]字节:\n",mytime_now(),inet_ntoa(addr.sin_addr),ntohs(addr.sin_port), sendCnt);
	//打印报文
	print_hex(sendbuf, sendCnt, 32);
	//TODO
	pkg_free(recvPkg);

	/*
	//循环解包 TODO 断包问题未解决，udp不考虑断包问题
	pkg_t recvPkg;
	if(pkg_unpack(buf, sizeof(buf), &recvPkg, errmsg)==-1){
		fprintf(stderr, "拆包失败:%s\n", errmsg);
		return;//直接扔掉
	}
	//解包成功
	int retno=0;
	switch(recvPkg.mtype){
	case MSG_LOGIN:
		retno=user_service_login(&recvPkg.userinfo, inet_ntoa(addr.sin_addr), 
				ntohs(addr.sin_port), errmsg);
		break;
	case MSG_REG:
		retno=user_service_reg(&recvPkg.userinfo, errmsg);
		break;
	case MSG_HEART:
		retno=user_service_heart(&recvPkg.userinfo, inet_ntoa(addr.sin_addr), 
				ntohs(addr.sin_port), errmsg);
		break;
	case MSG_LOGOUT:
		retno=user_service_logout(&recvPkg.userinfo, errmsg);
		break;
	case MSG_FRIEND_ADD:
		retno=friend_service_add(&recvPkg.userinfo, errmsg);
		break;
	case MSG_FRIEND_ADDNUM:
		retno=friend_service_getReqNum(&recvPkg.userinfo, errmsg);
		break;
	default:
		break;
	}
	//组装返回报文
	char sendbuf[59];
	pkg_packRet(sendbuf, recvPkg.frameno,retno, errmsg);
	
	//发送返回报文
	cnt=sendto(server, senyydbuf, sizeof(sendbuf), 0, (struct sockaddr*)&addr, sizeof(addr));
	
	printf("<<");
	printTime();
	printf(" 发送[%s:%d][%ld]字节:\n", inet_ntoa(addr.sin_addr),ntohs(addr.sin_port), cnt);
	//打印报文
	printHex(sendbuf, cnt, 16);
	*/
}


int server_sendto(char* destip, int destport, char* buf, int bufLen){
	struct sockaddr_in addr;
	addr.sin_family=AF_INET;
	addr.sin_addr.s_addr=inet_addr(destip);
	addr.sin_port=htons(destport);
	ssize_t cnt=sendto(server, buf, bufLen, 0, (struct sockaddr*)&addr, 
			sizeof(addr));
	printf("<<");
	printf("%s 发送<<系统消息>>[%s:%d][%ld]字节:\n", mytime_now(),inet_ntoa(addr.sin_addr),ntohs(addr.sin_port), cnt);
	//打印报文
	print_hex(buf, cnt, 16);
}


